package com.edu.atams.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.edu.atams.common.dto.NoticeDto;
import com.edu.atams.common.dto.NoticeInfoDto;
import com.edu.atams.common.lang.Result;
import com.edu.atams.entity.Class;
import com.edu.atams.entity.*;
import com.edu.atams.mapper.StudentMapper;
import com.edu.atams.mapper.SysUserMapper;
import com.edu.atams.security.AccountUser;
import com.edu.atams.service.*;
import com.edu.atams.utils.AsyncRequestUtil;
import com.edu.atams.utils.WeChatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author czj666
 * @since 2021-10-14
 */
@RestController
@RequestMapping("/notice")
public class NoticeController extends BaseController {

    @Autowired
    NoticeService noticeService;
    @Autowired
    NoticeClassService noticeClassService;
    @Autowired
    TeacherService teacherService;
    @Autowired
    StudentService studentService;
    @Autowired
    StudentMapper studentMapper;
    @Autowired
    SysUserService sysUserService;
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    ClassService classService;
    @Autowired
    GradeService gradeService;
    @Autowired
    WeChatUtil weChatUtil;
    @Autowired
    AsyncRequestUtil asyncRequestUtil;

    private SysUser getSysUser(){
        String username = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
        return sysUserService.getOne(new QueryWrapper<SysUser>().eq("username", username));
    }

    @GetMapping("/list4Student")
    public Result list4Student(String title){
        Integer userId = this.getSysUser().getId();
        int classId = studentClassService.getCurrentClassIdByStudentId(studentService.getOne(new QueryWrapper<Student>()
            .eq("user_id", userId)).getId());
        Page<NoticeInfoDto> pageData = noticeService.page4Student(getPage(),classId,userId,title);

        return Result.succ(pageData);
    }

    @GetMapping("/list4Teacher")
    public Result list4Teacher(String title){
        Page<NoticeInfoDto> pageData = noticeService.page(getPage(),
                new QueryWrapper<Notice>()
                        .eq("publisherId",this.getSysUser().getId())
                        .like(StrUtil.isNotBlank(title),"title",title)
                        .orderByDesc("create_time")
        );
        // 转为用于显示通知信息的对象
        List<NoticeInfoDto> noticeInfoDtos = new ArrayList<>();
        NoticeInfoDto noticeInfoDto = null;
        StringBuilder sb = new StringBuilder();
        // 查询所有收件人名称
        for (Notice notice : pageData.getRecords()) {
            noticeInfoDto = new NoticeInfoDto();
            BeanUtil.copyProperties(notice,noticeInfoDto);
            List<NoticeClass> noticeClasses = noticeClassService.list(new QueryWrapper<NoticeClass>().eq("notice_id", notice.getId()));
            if (noticeClasses.size()==1 && noticeClasses.get(0).getIsAll() == 0){
                Class myClass = classService.getById(noticeClasses.get(0).getClassId());
                myClass.setGrade(gradeService.getById(myClass.getGradeId()));
                sb.append(myClass.getGrade().getYear()).append(myClass.getGrade().getName()).append(myClass.getName()).append("：");
                String[] userIds = noticeClasses.get(0).getSysUserIds().split(",");
                List<Student> students = studentService.list(new QueryWrapper<Student>().in("user_id", Arrays.asList(userIds)));
                students.forEach(student -> {
                    sb.append(student.getSchoolno()).append("-").append(student.getName()).append("、");
                });
            }else{
                noticeClasses.forEach(noticeClass -> {
                    noticeClass.setMyClass(classService.getById(noticeClass.getClassId()));
                    noticeClass.getMyClass().setGrade(gradeService.getById(noticeClass.getMyClass().getGradeId()));
                    sb.append(noticeClass.getMyClass().getGrade().getYear()).append(noticeClass.getMyClass().getGrade().getName()).append(noticeClass.getMyClass().getName()).append("、");
                });
            }
            if (sb.length() != 0) sb.deleteCharAt(sb.length()-1);
            noticeInfoDto.setAddressee(sb.toString());
            noticeInfoDtos.add(noticeInfoDto);
            sb.setLength(0);
        }
        pageData.setRecords(noticeInfoDtos);
        return Result.succ(pageData);
    }

    @GetMapping("/info/{id}")
    public Result info(@PathVariable String id){
        Notice notice = noticeService.getById(id);
        NoticeInfoDto noticeInfoDto = new NoticeInfoDto();
        BeanUtil.copyProperties(notice,noticeInfoDto);
        StringBuilder sb = new StringBuilder();
        List<NoticeClass> noticeClasses = noticeClassService.list(new QueryWrapper<NoticeClass>().eq("notice_id", notice.getId()));
        if (noticeClasses.size()==1 && noticeClasses.get(0).getIsAll() == 0){
            Class myClass = classService.getById(noticeClasses.get(0).getClassId());
            myClass.setGrade(gradeService.getById(myClass.getGradeId()));
            sb.append(myClass.getGrade().getYear()).append(myClass.getGrade().getName()).append(myClass.getName()).append("：");
            String[] userIds = noticeClasses.get(0).getSysUserIds().split(",");
            List<Student> students = studentService.list(new QueryWrapper<Student>().in("user_id", Arrays.asList(userIds)));
            students.forEach(student -> {
                sb.append(student.getSchoolno()).append("-").append(student.getName()).append("、");
            });
        }else{
            noticeClasses.forEach(noticeClass -> {
                noticeClass.setMyClass(classService.getById(noticeClass.getClassId()));
                noticeClass.getMyClass().setGrade(gradeService.getById(noticeClass.getMyClass().getGradeId()));
                sb.append(noticeClass.getMyClass().getGrade().getYear()).append(noticeClass.getMyClass().getGrade().getName()).append(noticeClass.getMyClass().getName()).append("、");
            });
        }
        if (sb.length() != 0) sb.deleteCharAt(sb.length()-1);
        noticeInfoDto.setAddressee(sb.toString());
        return Result.succ(noticeInfoDto);
    }

    /**
     * 保存通知信息
     * @param noticeDto
     * @return
     * @throws Exception
     */
    @PostMapping("/save")
    public Result save (@RequestBody NoticeDto noticeDto){
        Integer userId = this.getSysUser().getId();
        noticeDto.getNotice().setPublisherid(userId);
        noticeDto.getNotice().setNickname(teacherService.getOne(new QueryWrapper<Teacher>().eq("user_id",userId)).getName());
        noticeDto.getNotice().setCreateTime(new Date());
        noticeService.save(noticeDto.getNotice());

        List<Integer> classIds = new ArrayList<>();
        // 用于发送微信消息推送
        List<String> openIds = new ArrayList<>();
        noticeDto.getNoticeClasses().forEach(n -> {
            // 对每个要发送的班级存储的关联通知id
            n.setNoticeId(noticeDto.getNotice().getId());
            classIds.add(n.getClassId());
        });
        // 如果选定的是指定人员(只能对某一个班指定人员)，而非全班人员
        if(noticeDto.getNoticeClasses().get(0).getIsAll() == 0) {
            // 前端显示的是student数据,将student的id集合转为userId集合
            String[] studentIds = noticeDto.getNoticeClasses().get(0).getSysUserIds().split(",");
            List<Integer> userIds = studentMapper.getUserIdsByStudentIds(studentIds);
            // 将其拼成为逗号隔开的字符串进行存储
            noticeDto.getNoticeClasses().get(0).setSysUserIds(StrUtil.join(",", userIds));

            openIds.addAll(sysUserService.listByIds(userIds).stream().map(SysUser::getOpenid).collect(Collectors.toList()));
        }else{
            openIds.addAll(sysUserMapper.getStudentOpenIdsByClassIds(classIds));
        }
        noticeClassService.saveBatch(noticeDto.getNoticeClasses());

        // 进行消息推送通知
        // 家庭作业
        if (noticeDto.getNotice().getType() == 1){
            asyncRequestUtil.sendHomeworkNotice(openIds, noticeDto);
        }else if (noticeDto.getNotice().getType() == 2 || noticeDto.getNotice().getType() == 3){
            // 校内通知、学校公告
            asyncRequestUtil.sendSchoolNotice(openIds, noticeDto);
        }
        return Result.succ("");
    }

    @GetMapping("/edit/{id}")
    public Result edit(@PathVariable Integer id){
        Notice notice = noticeService.getById(id);
        List<Class> classes = classService.list(new QueryWrapper<Class>().
                inSql("id", "select class_id from notice_class where notice_id = " + id));

        List<String> addressee =  classes.stream().map(c -> {
            c.setGrade(gradeService.getById(c.getGradeId()));
            return c.getGrade().getYear()+c.getGrade().getName()+c.getName();
        }).collect(Collectors.toList());

        return Result.succ(MapUtil.builder()
                .put("notice",notice)
                .put("addressee",addressee)
                .build()
        );
    }

    @PostMapping("/update")
    public Result update(@RequestBody Notice notice){
        noticeService.update(new UpdateWrapper<Notice>()
                .set("title",notice.getTitle())
                .set("content",notice.getContent())
                .set("type",notice.getType())
                .eq("id",notice.getId()));
        return Result.succ("");
    }

    @PostMapping("/delete")
    public Result delete(@RequestBody Integer[] ids){
        noticeService.removeByIds(Arrays.asList(ids));
        noticeClassService.remove(new QueryWrapper<NoticeClass>().in("notice_id",ids));
        return Result.succ("");
    }

}
